package com.itheima.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.pojo.Permission;
import com.itheima.pojo.Role;
import com.itheima.pojo.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/*
 * 测试 小明不具有删除检查项功能
 * */
@Component
public class SpringSecurityUserService implements UserDetailsService {
    @Reference
    private UserService userService;

    /*
    * 访问已配置放行的资源,不需要登录
    * 访问被拦截的资源,则需要先登录
    * 登录校验过程:security框架调用内部"controller",
    又根据配置的user-service-ref调用自定义权限类,并执行类中的重写方法
    * 只根据前台用户输入的用户名,调用dao层的查询该用户的基本信息/角色信息/权限信息,并把角色和权限添加到List集合中
    * 最后返回封装了用户名,数据库查询得到的密码,和角色/权限集合数据的框架User对象(非自定义的),
    * 然后security内部进行密码(加密的60位)比对,和为用户授权等操作,密码比对一致则登录成功
    * */
    //根据用户名查询用户信息
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //远程调用dao层服务,通过前台用户名查询数据库,是否有对应用户信息
        User user = userService.findByUsername(username);
        if (user == null) {
            //用户名不存在 ,登录失败
            return null;
        }
        int b = 1;

        //定义权限集合,用于封装用户具有的角色和权限
        List<GrantedAuthority> list = new ArrayList<>();
        //获取用户的所有角色
        Set<Role> roles = user.getRoles();

        //遍历用户所有角色
        for (Role role : roles) {
            //将角色添加到权限集合中,授予角色
            list.add(new SimpleGrantedAuthority(role.getKeyword()));
            //获取每个角色的所有权限
            Set<Permission> permissions = role.getPermissions();
            //遍历权限
            for (Permission permission : permissions) {
                //授予权限
                list.add(new SimpleGrantedAuthority(permission.getKeyword()));
            }
        }

        /*
         * 返回的User对象后的操作: security内部先进行用户名和密码校验,校验通过后登录,
         * 该用户操作页面时,如果页面功能方法上设置了@PreAuthorize('CHECKITEM_DELETE')权限注解,
         * 则会根据该用户拥有的权限集合中是否存在注解中设置的权限,进行比对判断,如果集合中存在,则拥有该权限,反之不拥有
         * */
        org.springframework.security.core.userdetails.User userDetails = new org.springframework.security.core.userdetails.User(username, user.getPassword(), list);

        return userDetails;
    }
}
